# [JS进阶]proto、prototype、继承三者的关系就这么简单
# 核心四句
- 1、所有对象都有__proto__属性来标识自己所继承的原型;
- 2、函数才有prototype属性;
- 3、创建函数时,JS会为这个函数自动添加prototype属性,值是一个有 constructor 属性的对象;
- 4、函数当作构造函数调用(通过new调用),JS会帮助创建构造函数的实例,实例通过设置自己的__proto__指向构造函数的prototype来实现继承;
# 实例解析
# 1、定义对象和函数
//字面量定义对象
let a = {};
//构造函数定义对象
let b = new Object();
//定义函数
function f(){};
//函数作为构造函数创建实例
let c = new f();
# 2、输出比较
在浏览器的控制台console中输入上述定义的对象和函数,进行_proto_和prototype的比较:

# 3、输出解析
# 1)所有对象都有__proto__属性来标识自己所继承的原型
比教上述所有输出的截图:无论对象还是函数,所有的输出都含有__proto__,为什么函数也有__proto__呢?因为函数本质上是特殊的对象,所有函数也是有__proto__的;从中可以验证所有对象都有__proto__属性来标识自己所继承的原型 。为了验证函数也是对象可以使用instanceof进行判断:
Function instanceof Object // true
# 2)函数才有prototype属性
上图中,只有f和Object输出中才有prototype,说明他们都是函数,对于f我们很容易判断,因为在定义时就决定了它时函数的事实,但是Object也是函数吗?不妨同样使用instanceof进行判断:
Object instanceof Function // true
从结果我们可以得出:Object底层定义为函数,我们通过new关键字调用的时候,就将Object作为构造函数使用的。
# 3)创建函数时,JS会为这个函数自动添加prototype属性,值是一个有 constructor 属性的对象
输出函数f的prototype,其实质是一个包含constructor属性的对象;
# 4)函数当作构造函数调用(通过new调用),JS会帮助创建构造函数的实例,实例通过设置自己的__proto__指向构造函数的prototype来实现继承
这句话从本质上阐述了js中继承的实现,即通过构造函数创建实例对象,实例的__proto__其实指向其构造函数的prototye属性;同样,我们用代码来验证下:
a.__proto__ === Object.prototype //true
b.__proto__ === Object.prototype //true
c.__proto__ === f.prototype //true
注意:字面量方式创建对象其底层也是通过new Object实现的,所有let a = {} 等价于 let a = new Object()。
# 4、原型和继承图
上图为原型链图,我们对上图进行人为的分区处理,大致分为四个区域,我们不妨将上面的分析和核心四句和原型链图对应起来理解:
- 1、
Function instanceof Object // trueObject instanceof Function // true(区域1),当然到底是先有鸡还是先有蛋的探究这里就不深入了; - 2、对最底层
Object继续进行原型跟踪,最终__proto__为null(区域1); - 3、定义的函数通过new关键字调用,生成新的函数实例的
__proto__继承了构造函数.prototype(区域2); - 4、函数的
prototype属性的构造函数constructor指向函数本身(区域1,2,3)f === f.prototype.constructor //true Function === Object.prototype.constructor //true Object === Object.prototype.constructor
# 5、小结
在javascript中,通过__proto__和prototype的合作实现了原型链,以及对象的继承。另外,对于作为构造函数的函数而言,可以使用prototype存放要共享的属性和方法,也可以设置prototype指向现存的对象来继承该对象。 对于任何对象而言,其自身的__proto__指向自己构造函数的prototype属性,通过obj.proto.proto...一层一层的调用实现了原型链。其中包括操作符instanceof本质上是通过探测obj.proto.proto... 是否最终等于构造函数constructor.prototype来验证obj是否是构造函数constructor的实例。
